Skip to content

Use act for a local CI startup script#6171

Open
MichaelSpece wants to merge 2 commits intoreflex-dev:mainfrom
MichaelSpece:codex/act-local-ci-script
Open

Use act for a local CI startup script#6171
MichaelSpece wants to merge 2 commits intoreflex-dev:mainfrom
MichaelSpece:codex/act-local-ci-script

Conversation

@MichaelSpece
Copy link
Copy Markdown

@MichaelSpece MichaelSpece commented Mar 12, 2026

Summary

  • replace the startup test script with an act-driven local CI entrypoint that runs the same Reflex workflow jobs
  • document the new local CI flow in CONTRIBUTING.md
  • keep self-hosted mode explicit and scrub known host-only env vars in that path

Notes

I could verify script parsing and job selection locally, but not full Docker-backed workflow execution in the container I used.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 12, 2026

Greptile Summary

This PR replaces the previous run_all_tests.sh startup script with an act-driven local CI entrypoint that mirrors the same GitHub Actions jobs (unit-tests, integration-app-harness, benchmarks, check_latest_node) developers would encounter in CI, and documents the new workflow in CONTRIBUTING.md.

Key points:

  • The script is well-structured with clear helper functions and sensible environment-variable overrides for platform images, Python versions, and state manager selection.
  • A Bash compatibility bug exists: expanding empty arrays ("${act_env_prefix[@]}", "${extra_act_args[@]}") under set -euo pipefail will abort the script with an unbound variable error on Bash ≤ 4.3 (including macOS's default Bash 3.2). The standard fix is "${arr[@]+"${arr[@]}"}"
  • ensure_act checks executability with [[ -x "$ACT_BIN" ]], which only works for absolute paths; a user setting ACT_BIN=act (bare name) gets a misleading "install act" error instead of a path-resolution failure.
  • CONTRIBUTING.md lists three scrubbed variables in self-hosted mode but the script actually scrubs four — GITHUB_CODESPACE_TOKEN is omitted from the docs.

Confidence Score: 3/5

  • Safe to merge for users on modern Bash, but will silently break on macOS default shell and other Bash < 4.4 environments due to the empty-array expansion bug.
  • The bash compatibility issue with empty array expansion under set -u is a real runtime failure on macOS (Bash 3.2) and any system with Bash ≤ 4.3 — a common developer environment. Combined with the documentation inaccuracy around scrubbed variables and the ensure_act edge case, the script needs a small but concrete fix before it can be relied upon across all supported environments.
  • scripts/run_all_tests.sh — the empty array expansion pattern and ensure_act logic need attention.

Important Files Changed

Filename Overview
scripts/run_all_tests.sh New act-driven local CI entrypoint; contains a Bash compatibility bug with empty array expansion under set -u on Bash < 4.4, a misleading error path in ensure_act for bare-name ACT_BIN values, and a minor doc/code inconsistency around which env vars are scrubbed in self-hosted mode.
CONTRIBUTING.md Adds clear documentation for the new act-based local CI flow; omits GITHUB_CODESPACE_TOKEN from the list of variables scrubbed in self-hosted mode, which is inconsistent with the actual script behaviour.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A([bash scripts/run_all_tests.sh args...]) --> B{-h / --help?}
    B -- yes --> C[show_help & exit 0]
    B -- no --> D[resolve ACT_BIN via command -v act]
    D --> E[ensure_act\nvalidates binary exists & is executable]
    E -- fail --> F[error: install act & exit 1]
    E -- ok --> G{is_list_mode args?}
    G -- yes --> H[skip Docker check]
    G -- no --> I{docker_daemon_available\nOR self_hosted_mode_enabled?}
    I -- no --> J[error: Docker required & exit 1]
    I -- yes --> H
    H --> K[configure_platform_args\nset -P ubuntu-latest= & -P ubuntu-22.04=]
    K --> L[configure_self_hosted_env\noptionally prepend env -u vars]
    L --> M[cd repo_root]
    M --> N[run_job: unit-tests\nunit_tests.yml, ubuntu-latest, python 3.13]
    N --> O[run_job loop split 1 & 2:\nintegration-app-harness\nintegration_app_harness.yml]
    O --> P{REFLEX_ACT_SKIP_BENCHMARKS?}
    P -- no --> Q[run_job: benchmarks\nperformance.yml]
    P -- yes --> R
    Q --> R[run_job loop split 1 & 2:\ncheck_latest_node\ncheck_node_latest.yml]
Loading

Last reviewed commit: 265101f

Comment on lines +154 to +161
"${act_env_prefix[@]}" "${ACT_BIN}" \
"${ACT_EVENT}" \
"${platform_args[@]}" \
-W ".github/workflows/${workflow}" \
-j "${job}" \
"$@" \
"${extra_act_args[@]}"
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty array expansion breaks with set -u on Bash < 4.4

The script uses set -euo pipefail at the top, and both "${act_env_prefix[@]}" (here in run_job) and "${extra_act_args[@]}" (line 82 in require_runner_support) will cause a fatal unbound variable error when those arrays are empty on Bash ≤ 4.3 and macOS's default Bash 3.2.

Reproducer on Bash 3.2 / 4.3:

set -u; arr=(); echo "${arr[@]}"
# bash: arr[@]: unbound variable

The standard bash-safe idiom is "${arr[@]+"${arr[@]}"}" which expands to nothing when empty and to the array elements when non-empty.

Affected locations:

  • scripts/run_all_tests.sh:154"${act_env_prefix[@]}"
  • scripts/run_all_tests.sh:82is_list_mode "${extra_act_args[@]}"
Suggested change
"${act_env_prefix[@]}" "${ACT_BIN}" \
"${ACT_EVENT}" \
"${platform_args[@]}" \
-W ".github/workflows/${workflow}" \
-j "${job}" \
"$@" \
"${extra_act_args[@]}"
}
"${act_env_prefix[@]+"${act_env_prefix[@]}"}" "${ACT_BIN}" \
"${ACT_EVENT}" \
"${platform_args[@]}" \
-W ".github/workflows/${workflow}" \
-j "${job}" \
"$@" \
"${extra_act_args[@]+"${extra_act_args[@]}"}"

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I fixed both empty-array call sites in 93d81e7 using the arr[@]+... pattern so the script no longer trips on Bash 3.2/4.3 under set -u.

CONTRIBUTING.md Outdated
bash scripts/run_all_tests.sh -l
```

If Docker is unavailable and you still want to run against your host environment, set `REFLEX_ACT_ALLOW_SELF_HOSTED=1`. In that mode the script scrubs `CODESPACE_NAME`, `GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN`, and `PYTHONSAFEPATH` to reduce host-specific drift. Set `REFLEX_ACT_SELF_HOSTED_PRESERVE_HOST_ENV=1` if you need the raw host environment instead.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation omits GITHUB_CODESPACE_TOKEN from the list of scrubbed variables

The CONTRIBUTING.md describes three scrubbed variables (CODESPACE_NAME, GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN, PYTHONSAFEPATH), but scripts/run_all_tests.sh lines 129–135 also unsets GITHUB_CODESPACE_TOKEN. A user who needs that token preserved (e.g., for Codespaces auth in self-hosted mode) would not know to set REFLEX_ACT_SELF_HOSTED_PRESERVE_HOST_ENV=1.

Suggested change
If Docker is unavailable and you still want to run against your host environment, set `REFLEX_ACT_ALLOW_SELF_HOSTED=1`. In that mode the script scrubs `CODESPACE_NAME`, `GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN`, and `PYTHONSAFEPATH` to reduce host-specific drift. Set `REFLEX_ACT_SELF_HOSTED_PRESERVE_HOST_ENV=1` if you need the raw host environment instead.
If Docker is unavailable and you still want to run against your host environment, set `REFLEX_ACT_ALLOW_SELF_HOSTED=1`. In that mode the script scrubs `CODESPACE_NAME`, `GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN`, `GITHUB_CODESPACE_TOKEN`, and `PYTHONSAFEPATH` to reduce host-specific drift.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You were right here too. I updated the CONTRIBUTING text in 93d81e7 so the self-hosted scrub list includes GITHUB_CODESPACE_TOKEN.

Comment on lines +60 to +71
ensure_act() {
if [[ -n "$ACT_BIN" && -x "$ACT_BIN" ]]; then
return 0
fi

cat >&2 <<'EOF'
Error: act is required to run the local CI workflow script.

Install it from https://nektosact.com/installation/ or set ACT_BIN to an existing binary.
EOF
exit 1
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensure_act reports "not installed" when ACT_BIN is set to a bare name

[[ -x "$ACT_BIN" ]] performs a filesystem test against the literal path. If the user sets ACT_BIN=act (a bare name, not an absolute path), the test checks for ./act in the current directory and fails — even when act is available on PATH. The misleading "act is required / install it" error message surfaces instead of "the specified binary is not executable or not found".

A safer check would use command -v to honour PATH resolution:

ensure_act() {
  if [[ -n "$ACT_BIN" ]] && command -v "$ACT_BIN" >/dev/null 2>&1; then
    # Resolve to full path so later -x checks work
    ACT_BIN="$(command -v "$ACT_BIN")"
    return 0
  fi

  cat >&2 <<'EOF'
Error: act is required to run the local CI workflow script.

Install it from https://nektosact.com/installation/ or set ACT_BIN to an existing binary.
EOF
  exit 1
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. 93d81e7 now resolves ACT_BIN through command -v before validating it, so bare names like ACT_BIN=act work instead of falling into the misleading not-installed path.

Copy link
Copy Markdown
Collaborator

@masenf masenf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be honest this seems like a lot of extra shell script to maintain to run the tests that can already be run pretty effectively via pytest.

i'm also a little skeptical of the unofficial docker images being used.

@MichaelSpece
Copy link
Copy Markdown
Author

Fair pushback. My intent here is not to replace the normal pytest loop; the direct unit-test command still stays the fast path in CONTRIBUTING. This script is an opt-in way to exercise a representative subset of the existing GitHub Actions jobs locally, since some failures show up in workflow/setup parity rather than in pytest alone.

On the images, agreed they are unofficial. I used them as a pragmatic act default, not because I think that tradeoff should be hidden. If the team would prefer, I can make the platform mapping more explicit/configured instead of defaulting it.

I also pushed 93d81e7 for the three smaller issues Greptile called out: the Bash empty-array compatibility case, bare-name ACT_BIN resolution, and the missing GITHUB_CODESPACE_TOKEN mention in the docs.

@MichaelSpece MichaelSpece changed the title Use act for the local CI startup script Use act for a local CI startup script Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants